/**
 * @author WY
 * @since 2023/04
 */
import { ColorSchema, CSMesh, MathTool, RENDERORDER } from '@amcax/base';
import { ctx2, dataManager } from '@app-cad/module';
import {
  Box3,
  Color,
  DoubleSide,
  MeshPhongMaterial,
  Texture,
} from 'three-legacy';
import {
  getModelMaterial,
  getPlaneBox,
  Picker3D,
  PickerMgr,
  Renderer3D,
  RendererMgr,
} from '@amcax/renderer';

type BrushAttrs = {
  color?: Array<number> | string;
  texture?: Texture;
  transparency?: number;
  showGlass?: boolean;
  planeBox?: Box3;
};
export function getBrushMeshMaterial(attrs: BrushAttrs) {
  const transparency = attrs.transparency ? attrs.transparency : 0;
  const box3 = attrs.planeBox;
  if (attrs.color) {
    return new MeshPhongMaterial({
      vertexColors: false,
      color:
        attrs.color instanceof Array
          ? new Color().fromArray(attrs.color)
          : new Color(attrs.color),
      shininess: 5,
      polygonOffset: true,
      polygonOffsetFactor: 0.75,
      polygonOffsetUnits: 0.75,
      side: DoubleSide,
      emissive: new Color().setHex(ColorSchema.emissive.default),
      transparent: transparency > 0 ? true : false,
      opacity: transparency > 0 ? transparency : 1,
    });
  } else {
    const texture = attrs.texture;
    if (box3) {
      const w = box3.max.x - box3.min.x;
      const y = box3.max.y - box3.min.y;
      const a = Math.min(w, y);
      const b = Math.max(w, y);
      const textureSize = 900;
      texture.repeat.set(b / textureSize, a / textureSize);
    }
    return new MeshPhongMaterial({
      vertexColors: false,
      map: texture,
      shininess: 5,
      polygonOffset: true,
      polygonOffsetFactor: 0.75,
      polygonOffsetUnits: 0.75,
      side: DoubleSide,
      emissive: new Color().setHex(ColorSchema.emissive.default),
      // transparent: transparency > 0 ? true : false,
      // opacity: 1 - transparency,
    });
  }
}
export function setMaterialByDxid(
  dxid: string,
  faceIndex: number,
  materialId: number,
) {
  // 设置材质
  const material = dataManager.getMaterials(materialId);
  const textureUrl = material.texture;
  const color = material.color;
  const originModel = PickerMgr.getPicker<Picker3D>('3d').getModelMesh(dxid);
  const { shape, placement } = dataManager.getObjectInfoByDxid(dxid);
  let texture;
  if (textureUrl) {
    texture = dataManager.getTextureMap(textureUrl);
  }
  if (faceIndex === -1) {
    // 体渲染
    if (texture) {
      const planeBox = new Box3().setFromObject(originModel);
      originModel.material = getBrushMeshMaterial({ texture, planeBox });
      originModel.setRenderOrder(RENDERORDER.MODEL_BRUSHED);
    } else if (color) {
      originModel.material = getBrushMeshMaterial({ color });
      originModel.setRenderOrder(RENDERORDER.MODEL_BRUSHED);
    }
  } else {
    // 面渲染
    const shapeInfo = dataManager.getShapeData(shape);
    const faceData = shapeInfo.faces[faceIndex];
    const csys = MathTool.createCsysFromPlacement(placement);
    const faceGeo = RendererMgr.getRender<Renderer3D>('3d').handleMesh(
      shapeInfo.positions,
      shapeInfo.normals,
      faceData,
      csys,
    );
    let material;
    if (textureUrl) {
      const planeBox = getPlaneBox(faceData, faceGeo, csys);
      const texture = dataManager.getTextureMap(textureUrl);
      material = getBrushMeshMaterial({ texture: texture, planeBox });
    } else {
      material = getBrushMeshMaterial({ color: color });
    }
    const coloredFaceArray = originModel.children.filter((item) => {
      return (item as CSMesh).modelDxid === `${dxid}:f${faceIndex}`;
    });
    let coloredMesh = coloredFaceArray[0] as CSMesh;
    if (coloredMesh) {
      coloredMesh.material = material;
    } else {
      coloredMesh = new CSMesh({
        geometry: faceGeo,
        material: material,
        modelDxid: `${dxid}:f${faceIndex}`,
        shapeId: shape,
        placement: placement,
        visibility: true,
        renderOrder: RENDERORDER.FACE_BRUSHED,
      });
      coloredMesh.addTo(originModel);
    }
  }
  ctx2.viewer.requestRender();
}

export function clearMaterialByDxid(dxid: string, faceIndex: number) {
  // 设置材质
  const originModel = PickerMgr.getPicker<Picker3D>('3d').getModelMesh(dxid);
  if (faceIndex === -1) {
    // 体渲染
    originModel.material = getModelMaterial();
    originModel.setRenderOrder(RENDERORDER.FACE);
  } else {
    // 面渲染
    const coloredFaceArray = originModel.children.filter((item) => {
      return (item as CSMesh).modelDxid === `${dxid}:f${faceIndex}`;
    });
    const coloredMesh = coloredFaceArray[0] as CSMesh;
    originModel.remove(coloredMesh);
  }
  ctx2.viewer.requestRender();
}
